/*******************************************************************************
 * Copyright (c) 2009 Kevin Bierhoff and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Kevin Bierhoff - initial API and implementation
 *******************************************************************************/
package com.googlecode.twelfdevtools.server;

import java.io.File;
import java.io.IOException;
import java.io.PipedReader;
import java.io.PipedWriter;
import java.io.PrintStream;
import java.io.Reader;

import org.eclipse.core.resources.IProject;
import org.eclipse.ui.console.ConsolePlugin;
import org.eclipse.ui.console.IConsole;
import org.eclipse.ui.console.MessageConsole;
import org.eclipse.ui.console.MessageConsoleStream;

import com.googlecode.twelfdevtools.console.TwelfConsoleErrorListener;


public class TwelfProcess {
	
	final private Process twelf;
	final private PrintStream stdIn;
	final private MessageConsole con;
	final private MessageConsoleStream display;
	final private PipedWriter pub;
	final private PipedReader twelfOutput;
	final private Thread t;
	
	/**
	 * @param project Directory from which to invoke Twelf, 
	 * or <code>null</code> to inherit the parent process's startup directory.
	 * @param twelfCommand The command for starting Twelf.
	 * @throws IOException
	 */
	public TwelfProcess(IProject project, String twelfCommand) throws IOException {
		File projectDir = project.getLocation().toFile();
		twelf = Runtime.getRuntime().exec(twelfCommand, null /*inherit environment*/, projectDir);
		stdIn = new PrintStream(twelf.getOutputStream());
		
		// set up pipe for Twelf output
		pub = new PipedWriter();
		twelfOutput = new PipedReader(pub);
		
		// set up Eclipse console
		con = new MessageConsole("Twelf Console", null);
		ConsolePlugin.getDefault().getConsoleManager().addConsoles(
				new IConsole[] { con });
		con.addPatternMatchListener(new TwelfConsoleErrorListener(project));
		con.activate();
		display = con.newMessageStream();
		t = new Thread(new Runnable() {
			public void run() {
				int c;
				try {
					while((c = twelf.getInputStream().read()) >= 0) {
						// write to pipe
						pub.write((char) c);
						// write to console
						display.write((char) c);
					}
					// attempt orderly shutdown
					System.out.println("Shutting down Twelf console");
					pub.close();
					display.close();
					ConsolePlugin.getDefault().getConsoleManager().removeConsoles(
							new IConsole[] { con });
				} 
				catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				// go home
			}
			
		});
		t.start();
	}
	
	public synchronized void issueCommand(String cmd) {
		stdIn.println(cmd);
		stdIn.flush();
	}
	
	public void make() {
		issueCommand("make");
	}
	
	public void loadFile(String fileName) {
		issueCommand("loadFile " + fileName);
	}
	
	public void quit() {
		issueCommand("quit");
	}
	
	public synchronized void kill() {
		twelf.destroy();
	}
	
	public Reader getStdOut() {
		return twelfOutput;
	}
	
	/**
	 * This currently doesn't work... should create a new process with the given command
	 * and shut down the old one, but that currently severs the output streams.
	 * @param project
	 * @param twelfCommand
	 */
	public synchronized void restart(IProject project, String twelfCommand) {
//		try {
//			File projectDir = project.getLocation().toFile();
//			Process newP = Runtime.getRuntime().exec(
//					twelfCommand, null /*inherit environment*/, projectDir);
//			if(twelf != null) {
//				quit();
//			}
//			twelf = newP;
//		} 
//		catch (IOException e) {
//			System.err.println("Error restarting server");
//			e.printStackTrace();
//		}
	}

	protected void finalize() {
		if(twelf != null)
			twelf.destroy();
	}

}
